/*
MICKEY-v2-bitslice - Bitslice implementation of MICKEY 2.0
Copyright (C) 2010 Deian Stefan

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "mickey_bitslice.h"
#include <string.h>
#include <stdint.h>
#include <stdio.h>

/* - CONSTANTS ------------------------------------------------------------- */

const uword RTAPS[100]={
/*  0 */ (~0),
/*  1 */ (~0),
/*  2 */   0 ,
/*  3 */ (~0),
/*  4 */ (~0),
/*  5 */ (~0),
/*  6 */ (~0),
/*  7 */   0 ,
/*  8 */   0 ,
/*  9 */ (~0),
/* 10 */   0 ,
/* 11 */   0 ,
/* 12 */ (~0),
/* 13 */ (~0),
/* 14 */   0 ,
/* 15 */   0 ,
/* 16 */ (~0),
/* 17 */   0 ,
/* 18 */   0 ,
/* 19 */ (~0),
/* 20 */ (~0),
/* 21 */ (~0),
/* 22 */ (~0),
/* 23 */   0 ,
/* 24 */   0 ,
/* 25 */ (~0),
/* 26 */   0 ,
/* 27 */   0 ,
/* 28 */ (~0),
/* 29 */   0 ,
/* 30 */   0 ,
/* 31 */   0 ,
/* 32 */   0 ,
/* 33 */   0 ,
/* 34 */   0 ,
/* 35 */   0 ,
/* 36 */   0 ,
/* 37 */ (~0),
/* 38 */ (~0),
/* 39 */   0 ,
/* 40 */   0 ,
/* 41 */ (~0),
/* 42 */ (~0),
/* 43 */   0 ,
/* 44 */   0 ,
/* 45 */ (~0),
/* 46 */ (~0),
/* 47 */   0 ,
/* 48 */   0 ,
/* 49 */   0 ,
/* 50 */ (~0),
/* 51 */   0 ,
/* 52 */ (~0),
/* 53 */   0 ,
/* 54 */ (~0),
/* 55 */   0 ,
/* 56 */ (~0),
/* 57 */   0 ,
/* 58 */ (~0),
/* 59 */   0 ,
/* 60 */ (~0),
/* 61 */ (~0),
/* 62 */   0 ,
/* 63 */ (~0),
/* 64 */ (~0),
/* 65 */ (~0),
/* 66 */ (~0),
/* 67 */ (~0),
/* 68 */   0 ,
/* 69 */   0 ,
/* 70 */   0 ,
/* 71 */ (~0),
/* 72 */ (~0),
/* 73 */   0 ,
/* 74 */   0 ,
/* 75 */   0 ,
/* 76 */   0 ,
/* 77 */   0 ,
/* 78 */   0 ,
/* 79 */ (~0),
/* 80 */ (~0),
/* 81 */ (~0),
/* 82 */ (~0),
/* 83 */   0 ,
/* 84 */   0 ,
/* 85 */   0 ,
/* 86 */   0 ,
/* 87 */ (~0),
/* 88 */ (~0),
/* 89 */ (~0),
/* 90 */ (~0),
/* 91 */ (~0),
/* 92 */ (~0),
/* 93 */   0 ,
/* 94 */ (~0),
/* 95 */ (~0),
/* 96 */ (~0),
/* 97 */ (~0),
/* 98 */   0 ,
/* 99 */   0 
};

const uword COMP0[100]= {
/*  0 */   0 ,
/*  1 */   0 ,
/*  2 */   0 ,
/*  3 */   0 ,
/*  4 */ (~0),
/*  5 */ (~0),
/*  6 */   0 ,
/*  7 */   0 ,
/*  8 */   0 ,
/*  9 */ (~0),
/* 10 */   0 ,
/* 11 */ (~0),
/* 12 */ (~0),
/* 13 */ (~0),
/* 14 */ (~0),
/* 15 */   0 ,
/* 16 */ (~0),
/* 17 */   0 ,
/* 18 */   0 ,
/* 19 */ (~0),
/* 20 */   0 ,
/* 21 */ (~0),
/* 22 */   0 ,
/* 23 */ (~0),
/* 24 */   0 ,
/* 25 */ (~0),
/* 26 */   0 ,
/* 27 */ (~0),
/* 28 */   0 ,
/* 29 */ (~0),
/* 30 */ (~0),
/* 31 */   0 ,
/* 32 */ (~0),
/* 33 */   0 ,
/* 34 */   0 ,
/* 35 */ (~0),
/* 36 */   0 ,
/* 37 */   0 ,
/* 38 */   0 ,
/* 39 */   0 ,
/* 40 */   0 ,
/* 41 */   0 ,
/* 42 */   0 ,
/* 43 */ (~0),
/* 44 */   0 ,
/* 45 */ (~0),
/* 46 */   0 ,
/* 47 */ (~0),
/* 48 */   0 ,
/* 49 */ (~0),
/* 50 */   0 ,
/* 51 */   0 ,
/* 52 */   0 ,
/* 53 */   0 ,
/* 54 */ (~0),
/* 55 */   0 ,
/* 56 */ (~0),
/* 57 */   0 ,
/* 58 */   0 ,
/* 59 */ (~0),
/* 60 */ (~0),
/* 61 */ (~0),
/* 62 */ (~0),
/* 63 */   0 ,
/* 64 */   0 ,
/* 65 */ (~0),
/* 66 */   0 ,
/* 67 */ (~0),
/* 68 */   0 ,
/* 69 */ (~0),
/* 70 */ (~0),
/* 71 */ (~0),
/* 72 */ (~0),
/* 73 */ (~0),
/* 74 */ (~0),
/* 75 */ (~0),
/* 76 */ (~0),
/* 77 */ (~0),
/* 78 */   0 ,
/* 79 */ (~0),
/* 80 */   0 ,
/* 81 */ (~0),
/* 82 */ (~0),
/* 83 */ (~0),
/* 84 */ (~0),
/* 85 */ (~0),
/* 86 */ (~0),
/* 87 */   0 ,
/* 88 */ (~0),
/* 89 */   0 ,
/* 90 */ (~0),
/* 91 */   0 ,
/* 92 */   0 ,
/* 93 */   0 ,
/* 94 */   0 ,
/* 95 */   0 ,
/* 96 */   0 ,
/* 97 */ (~0),
/* 98 */ (~0),
/* 99 */   0 ,
};

const uword COMP1[100]= {
/*  0 */   0 ,
/*  1 */ (~0),
/*  2 */   0 ,
/*  3 */ (~0),
/*  4 */ (~0),
/*  5 */   0 ,
/*  6 */   0 ,
/*  7 */ (~0),
/*  8 */   0 ,
/*  9 */ (~0),
/* 10 */ (~0),
/* 11 */ (~0),
/* 12 */ (~0),
/* 13 */   0 ,
/* 14 */   0 ,
/* 15 */ (~0),
/* 16 */   0 ,
/* 17 */ (~0),
/* 18 */   0 ,
/* 19 */   0 ,
/* 20 */   0 ,
/* 21 */ (~0),
/* 22 */ (~0),
/* 23 */   0 ,
/* 24 */ (~0),
/* 25 */   0 ,
/* 26 */ (~0),
/* 27 */ (~0),
/* 28 */ (~0),
/* 29 */   0 ,
/* 30 */ (~0),
/* 31 */ (~0),
/* 32 */ (~0),
/* 33 */ (~0),
/* 34 */   0 ,
/* 35 */   0 ,
/* 36 */   0 ,
/* 37 */ (~0),
/* 38 */ (~0),
/* 39 */   0 ,
/* 40 */ (~0),
/* 41 */   0 ,
/* 42 */ (~0),
/* 43 */ (~0),
/* 44 */ (~0),
/* 45 */   0 ,
/* 46 */   0 ,
/* 47 */   0 ,
/* 48 */   0 ,
/* 49 */ (~0),
/* 50 */   0 ,
/* 51 */   0 ,
/* 52 */   0 ,
/* 53 */ (~0),
/* 54 */   0 ,
/* 55 */ (~0),
/* 56 */ (~0),
/* 57 */ (~0),
/* 58 */   0 ,
/* 59 */   0 ,
/* 60 */   0 ,
/* 61 */ (~0),
/* 62 */ (~0),
/* 63 */ (~0),
/* 64 */ (~0),
/* 65 */ (~0),
/* 66 */ (~0),
/* 67 */   0 ,
/* 68 */ (~0),
/* 69 */   0 ,
/* 70 */ (~0),
/* 71 */ (~0),
/* 72 */ (~0),
/* 73 */   0 ,
/* 74 */ (~0),
/* 75 */ (~0),
/* 76 */ (~0),
/* 77 */ (~0),
/* 78 */   0 ,
/* 79 */   0 ,
/* 80 */   0 ,
/* 81 */ (~0),
/* 82 */   0 ,
/* 83 */   0 ,
/* 84 */   0 ,
/* 85 */   0 ,
/* 86 */ (~0),
/* 87 */ (~0),
/* 88 */ (~0),
/* 89 */   0 ,
/* 90 */   0 ,
/* 91 */   0 ,
/* 92 */ (~0),
/* 93 */   0 ,
/* 94 */   0 ,
/* 95 */ (~0),
/* 96 */ (~0),
/* 97 */   0 ,
/* 98 */   0 ,
/* 99 */   0 ,
};

const uword FB0[100]= {
/*  0 */ (~0),
/*  1 */ (~0),
/*  2 */ (~0),
/*  3 */ (~0),
/*  4 */   0 ,
/*  5 */ (~0),
/*  6 */   0 ,
/*  7 */ (~0),
/*  8 */ (~0),
/*  9 */ (~0),
/* 10 */ (~0),
/* 11 */ (~0),
/* 12 */ (~0),
/* 13 */ (~0),
/* 14 */ (~0),
/* 15 */   0 ,
/* 16 */   0 ,
/* 17 */ (~0),
/* 18 */   0 ,
/* 19 */ (~0),
/* 20 */ (~0),
/* 21 */ (~0),
/* 22 */ (~0),
/* 23 */ (~0),
/* 24 */ (~0),
/* 25 */ (~0),
/* 26 */ (~0),
/* 27 */ (~0),
/* 28 */ (~0),
/* 29 */   0 ,
/* 30 */   0 ,
/* 31 */ (~0),
/* 32 */ (~0),
/* 33 */   0 ,
/* 34 */   0 ,
/* 35 */   0 ,
/* 36 */   0 ,
/* 37 */   0 ,
/* 38 */   0 ,
/* 39 */ (~0),
/* 40 */ (~0),
/* 41 */ (~0),
/* 42 */   0 ,
/* 43 */   0 ,
/* 44 */ (~0),
/* 45 */   0 ,
/* 46 */   0 ,
/* 47 */ (~0),
/* 48 */   0 ,
/* 49 */ (~0),
/* 50 */   0 ,
/* 51 */ (~0),
/* 52 */   0 ,
/* 53 */   0 ,
/* 54 */ (~0),
/* 55 */   0 ,
/* 56 */ (~0),
/* 57 */ (~0),
/* 58 */ (~0),
/* 59 */ (~0),
/* 60 */   0 ,
/* 61 */ (~0),
/* 62 */   0 ,
/* 63 */ (~0),
/* 64 */   0 ,
/* 65 */ (~0),
/* 66 */   0 ,
/* 67 */   0 ,
/* 68 */   0 ,
/* 69 */   0 ,
/* 70 */   0 ,
/* 71 */   0 ,
/* 72 */   0 ,
/* 73 */   0 ,
/* 74 */   0 ,
/* 75 */ (~0),
/* 76 */ (~0),
/* 77 */   0 ,
/* 78 */ (~0),
/* 79 */   0 ,
/* 80 */   0 ,
/* 81 */   0 ,
/* 82 */ (~0),
/* 83 */ (~0),
/* 84 */   0 ,
/* 85 */ (~0),
/* 86 */ (~0),
/* 87 */ (~0),
/* 88 */   0 ,
/* 89 */   0 ,
/* 90 */ (~0),
/* 91 */ (~0),
/* 92 */ (~0),
/* 93 */   0 ,
/* 94 */   0 ,
/* 95 */ (~0),
/* 96 */ (~0),
/* 97 */   0 ,
/* 98 */   0 ,
/* 99 */   0 ,
};

const uword FB1[100]= {
/*  0 */ (~0),
/*  1 */ (~0),
/*  2 */ (~0),
/*  3 */   0 ,
/*  4 */ (~0),
/*  5 */ (~0),
/*  6 */ (~0),
/*  7 */   0 ,
/*  8 */   0 ,
/*  9 */   0 ,
/* 10 */   0 ,
/* 11 */ (~0),
/* 12 */ (~0),
/* 13 */ (~0),
/* 14 */   0 ,
/* 15 */ (~0),
/* 16 */   0 ,
/* 17 */   0 ,
/* 18 */ (~0),
/* 19 */ (~0),
/* 20 */   0 ,
/* 21 */   0 ,
/* 22 */   0 ,
/* 23 */ (~0),
/* 24 */   0 ,
/* 25 */   0 ,
/* 26 */ (~0),
/* 27 */ (~0),
/* 28 */   0 ,
/* 29 */   0 ,
/* 30 */ (~0),
/* 31 */   0 ,
/* 32 */ (~0),
/* 33 */ (~0),
/* 34 */   0 ,
/* 35 */   0 ,
/* 36 */   0 ,
/* 37 */ (~0),
/* 38 */ (~0),
/* 39 */   0 ,
/* 40 */   0 ,
/* 41 */   0 ,
/* 42 */   0 ,
/* 43 */   0 ,
/* 44 */ (~0),
/* 45 */ (~0),
/* 46 */   0 ,
/* 47 */ (~0),
/* 48 */ (~0),
/* 49 */   0 ,
/* 50 */   0 ,
/* 51 */   0 ,
/* 52 */ (~0),
/* 53 */   0 ,
/* 54 */   0 ,
/* 55 */   0 ,
/* 56 */ (~0),
/* 57 */   0 ,
/* 58 */   0 ,
/* 59 */ (~0),
/* 60 */   0 ,
/* 61 */   0 ,
/* 62 */ (~0),
/* 63 */   0 ,
/* 64 */ (~0),
/* 65 */ (~0),
/* 66 */   0 ,
/* 67 */ (~0),
/* 68 */   0 ,
/* 69 */ (~0),
/* 70 */   0 ,
/* 71 */   0 ,
/* 72 */ (~0),
/* 73 */   0 ,
/* 74 */ (~0),
/* 75 */   0 ,
/* 76 */   0 ,
/* 77 */   0 ,
/* 78 */ (~0),
/* 79 */ (~0),
/* 80 */ (~0),
/* 81 */ (~0),
/* 82 */   0 ,
/* 83 */ (~0),
/* 84 */ (~0),
/* 85 */ (~0),
/* 86 */ (~0),
/* 87 */ (~0),
/* 88 */   0 ,
/* 89 */   0 ,
/* 90 */   0 ,
/* 91 */   0 ,
/* 92 */   0 ,
/* 93 */   0 ,
/* 94 */ (~0),
/* 95 */   0 ,
/* 96 */   0 ,
/* 97 */   0 ,
/* 98 */   0 ,
/* 99 */ (~0),
};


/* - MICKEY INTERNALS ------------------------------------------------------ */

/* least non-negative residue of x mod M */
#define __mod(x,M)                                      \
   ( ( (x)>=(M) ) ? ( (x)-(M) ) :                       \
                 ( (x)<(0) ) ? ( (M)+(x) ) : (x) )      \

/* least non-negative residue of x mod M, assuming x<M */
#define __mod_low(x,M)                  \
   ( ( (x)<(0) ) ? ( (M)+(x) ) : (x) )  \

/* least non-negative residue of x mod M, assuming x>=0 */
#define __mod_high(x,M)                 \
   ( ( (x)>=(M) ) ? ( (x)-(M) ) : (x) ) \


/* 
   clock_r - clocks register R as described in Sec. 4.2 of the MICKEY
   specification.
   
   NOTE: all streams must use the same size IV, because the R registers of
   the streams need to be in the same position regardless of the control
   and input bits which might modify the state of each differently.
*/
static void clock_r(mickey_state *ctx, uword input_bits, uword control_bits) {
   int i,pos,pos1;
   uword *R;
   uword feedback_bits,R0;

   R=ctx->R;
   pos=ctx->R0_pos;

   ctx->R0_pos=__mod_low(ctx->R0_pos-1,100); /* shift Ri'=Ri-1 */

   feedback_bits=R[ctx->R0_pos]^input_bits; /* fb = R99^input_bits */

   /* R0' = fb ^ (R0 if control_bit) */
   R0 = feedback_bits ^ ( control_bits  & R[pos] );

   if(feedback_bits||control_bits) {
      for(i=1;i<100;i++) {
         pos1=__mod_high(pos+1,100);

         /* Ri' = Ri' ^ (fb if i \in RTAPS) ^ (Ri if control_bit) */
         R[pos]  = R[pos]
                 ^ ( feedback_bits & RTAPS[i] )
                 ^ ( control_bits  & R[pos1] );
         pos=pos1;
      }
   }
   R[ctx->R0_pos]=R0;
}

/* 
   clock_s - clocks register S as described in Sec. 4.2 of the MICKEY
   specification. The clocking of S doesn't benefit from the simple
   shift trick as in clocking R, so a direct implementation seems more
   optimal.
*/
static void clock_s(mickey_state *ctx, uword input_bits, uword control_bits) {
   int i;
   uword *S;
   uword feedback_bits,Si_prev,tmp,S0,S99;

   S=ctx->S;

   feedback_bits=S[99]^input_bits; /* fb = S99^input_bits */

   /* S0' = FB0[0]&fb if control_bit=0
          = FB1[0]&fb if control_bit=1
      But FB0[0]=FB[1]=1, so S0'=fb
    */
   S0 = feedback_bits;

   /* S99' = S98 if control_bit = 0 //since FB0[99]=0
           = S98 ^ fb if control_bit =1 //since FB1[99]=1
      So, S99' = S98 ^ (fb&control_bit)
  */
   S99 = S[98] ^ (feedback_bits & control_bits);

   Si_prev=S[0];

   if(feedback_bits) {
      for(i=1;i<99;i++) {
         tmp=S[i];
         S[i] = Si_prev 
              ^ ( (S[i]^COMP0[i]) & (S[i+1]^COMP1[i]))
              ^ ( feedback_bits &
                 ( ((~control_bits) & FB0[i]) ^ (control_bits & FB1[i]) )
                );
         Si_prev=tmp;
      }
   } else {
      for(i=1;i<99;i++) {
         tmp=S[i];
         S[i] = Si_prev ^ ( (S[i]^COMP0[i]) & (S[i+1]^COMP1[i]));
         Si_prev=tmp;
      }
   }
   S[0]=S0; S[99]=S99;
}

/*
   clock_kg - clocks registers R and S according to Section 4.4 of the
   MICKEY 2.0 specification document.
*/
void clock_kg(mickey_state *ctx, uword mixing, uword input_bits) {
   uword control_bits_r, control_bits_s;
   uword input_bits_r, input_bits_s;

   control_bits_r=ctx->S[34] ^ ctx->R[__mod_high(ctx->R0_pos+67,100)];
   control_bits_s=ctx->S[67] ^ ctx->R[__mod_high(ctx->R0_pos+33,100)];

   /* if mixing input_bit_r=input_bit^S55 else input_bit_r=input_bit */
   input_bits_r=(mixing & ctx->S[50]) ^ input_bits;
   input_bits_s=input_bits;


   clock_r(ctx,input_bits_r,control_bits_r);
   clock_s(ctx,input_bits_s,control_bits_s);
}

/* - MICKEY EXTERNAL API --------------------------------------------------- */

/* 
   mickey_init - initialize registers to all-zeros
*/
void mickey_init(mickey_state *ctx) {
   memset(ctx->R,0,sizeof(ctx->R));
   memset(ctx->S,0,sizeof(ctx->S));
   memset(ctx->keys,0,sizeof(ctx->keys));
   memset(ctx->IVs,0,sizeof(ctx->IVs));
   ctx->R0_pos=0;
   ctx->key_set=ctx->IV_set=0;
   ctx->IVlen=0;
}


/*
   mickey_load_key - load a single key into the bitslice key registers
   This can be easilly rewritten to load all 32 or 64 (or whatever word-size)
   keys at the same time.

*/
int mickey_load_key(mickey_state *ctx, const uint8_t key[80]) {
   int i;

   if(ctx->key_set>=MICKEY_NR_STREAMS) {
      fprintf(stderr,"mickey_load_key: attempting to load too many keys!\n");
      return -1;
   }

   for(i=0;i<80;i++) {
      uword k=(uword)(((key[i/8]>>(7-(i%8)))&1))<<ctx->key_set;
      ctx->keys[i]|=k;
   }
   return ctx->key_set++;
}

/*
   mickey_load_IV - load a single IV into the bitslice IV registers
   This function is the same as the key loading function, with the exception
   of the addtional IVlen parameter -- note that this parameter should be
   the same for all the IVs being loaded.
   IVlen is in bits.
*/
int mickey_load_IV(mickey_state *ctx, const uint8_t *IV, uint32_t IVlen) {
   int i;//,j,count=0;

   if(ctx->IV_set>=MICKEY_NR_STREAMS) {
      fprintf(stderr,"mickey_load_IV: attempting to load too many IVs!\n");
      return -1;
   }
   if(ctx->IV_set==0) {
      if((IVlen>80) || (IVlen<0)) {
         fprintf(stderr,"mickey_load_IV: invalid IV length!\n");
         return -2;
      }
      ctx->IVlen=IVlen;
   } else if(ctx->IVlen!=IVlen) {
      fprintf(stderr,"mickey_load_IV: IV length does not math set length!\n");
      return -3;
   }

   for(i=0;i<ctx->IVlen;i++) {
      uword k=(uword)((IV[i/8]>>(7-(i%8)))&1)<<ctx->IV_set;
      ctx->IVs[i]|=k;
   }

   return ctx->IV_set++;
}

/* 
   mickey_setup - perform the key loading an initialization as detailed in 
   section 5 of the MICKEY 2.0 paper.
   NOTE: it is imperant to run the mickey_init and mickey_load_key (and 
   optionally mickey_load_IV) before running the setup.
*/
void mickey_setup(mickey_state *ctx) {
   int i;
   for(i=0;i<ctx->IVlen;i++) {
      clock_kg(ctx,(~0),ctx->IVs[i]);
   }
   for(i=0;i<80;i++) {
      clock_kg(ctx,(~0),ctx->keys[i]);
   }
   for(i=0;i<100;i++) {
      clock_kg(ctx,(~0),0);
   }
}

/* 
   mickey_keystream - returns the keystream output, bit-by-bit as described
   in Section 6 of the MICKEY 2.0 paper.
*/
uword mickey_keystream(mickey_state *ctx) {
   uword Z0=ctx->R[ctx->R0_pos]^ctx->S[0]; /* Z0=R0^S0 */
   clock_kg(ctx,0,0);
   return Z0;
}

/* 
   mickey_keystream_byte - returns a byte of keystream output for each stream
   so keystream[0]=byte for stream0,
      keystream[1]=byte for stream1,
      ...,
      keystream[N]=byte for streamN.

   NOTE: keystream should be properly allocated to sizeo: sizeof(uint8_t)*N
         where the number or streams N=MICKEY_NR_STREAMS
*/
void mickey_keystream_byte(mickey_state *ctx, uint8_t *keystream) {
   int i,j;
   uword Z0;

   memset(keystream,0,sizeof(uint8_t)*MICKEY_NR_STREAMS); /*clear buffer*/

   for(i=0;i<8;i++) { 
      Z0=ctx->R[ctx->R0_pos]^ctx->S[0]; /* Z0=R0^S0 */
      clock_kg(ctx,0,0);
      for(j=0;j<MICKEY_NR_STREAMS;j++) { 
         keystream[j]|=((Z0>>j)&1)<<(7-i);
      }
   }
}
